package com.finger.gulimall.product.web;

import com.finger.gulimall.product.entity.CategoryEntity;
import com.finger.gulimall.product.service.CategoryService;
import com.finger.gulimall.product.vo.Catelog2Vo;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;

@Controller
public class IndexController {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private CategoryService categoryService;

    @RequestMapping(value = {"/", "index.html"})
    public String index(Model model) {

        // TODO 查出所有得一级分类
        List<CategoryEntity> list = categoryService.getLevelOneList();

        model.addAttribute("data", list);
        return "index";
    }

    @ResponseBody
    @RequestMapping("/index/catalog")
    public Map<String, List<Catelog2Vo>> indexCatalog() {

        // 查询出所有的一级分类及其子类
        Map<String, List<Catelog2Vo>> resultMap = categoryService.getLevelTwoList();
        return resultMap;
    }

    /**
     * redisson使用读写锁
     *
     * @return
     */
    @ResponseBody
    @RequestMapping("hello")
    public String hello() throws InterruptedException {

        /*
            // 闭锁
            RCountDownLatch loco = redissonClient.getCountDownLatch("loco");
            // 等待
            loco.await();
            // 设置锁访问次数，达到该次数时会释放上边等待（await）的锁
            loco.trySetCount()
            loco.countDown();
        */
        /*
            // 信号量锁,
            // 可以用来做分布式限流
            RSemaphore semaphore = redissonClient.getSemaphore("lock");
            //获得信号
            semaphore.acquire();
            // 释放信号
            semaphore.release();
         */

        /*
        RTransaction transaction = redissonClient.createTransaction(TransactionOptions.defaults());
        transaction.rollback();
        transaction.commit();
         */
        /*
            读 读：跟没锁似的，
            读 写：读锁要等待写锁的逻辑执行完，读锁才能读
            写 写：线程安全，如果有多个写锁逻辑执行，写锁要排队等待
            写 读：读锁要等待写锁的逻辑执行完，读锁才能读

            // 读写锁，读的时候跟没锁似的，如果写锁有锁的情况下，读锁要等待写锁写完的过程读锁才能读
            // 获取读写锁
            RReadWriteLock readWrite = redissonClient.getReadWriteLock("readWrite");
            // 获取读锁
            RLock readLock = readWrite.readLock();
            // 获取写锁
            RLock writeLock = readWrite.writeLock();
         */

        // 获取锁,参数名相同获取的都是同一把锁
        RLock lock = redissonClient.getLock("my-lock");

        try {
            // 锁住，默认时长30秒，如果说业务逻辑执行的时间比锁的默认过期时长，则锁会’自续时长‘，直到业务逻辑结束
            // 如果当前业务逻辑没有执行完
            lock.lock(); // 阻塞式等待
            System.out.println("执行业务逻辑");
            Thread.sleep(10000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 解锁
            // 如果因为特殊原因该线程没有执行释放锁操作，锁会自动过期
            System.out.println("释放锁。。");
            lock.unlock();
        }
        return "hello";
    }
}
